#include <lib/string.h>
#include <lib/stdio.h>
#include <lib/unistd.h>
#include <sys/ioctl.h>
#include <sys/input.h>
#include <os/driver.h>
#include <driver/view/hal.h>
#include <driver/view/mouse.h>

#ifndef DEVICE_NAME
#define DEVICE_NAME "mouse"
#endif

//#define DEBUG_MOUSE_HAL

int ViewMouseOpen(view_mouse_t *mouse)
{
    mouse->handle = DeviceOpen(DEVICE_NAME, 0);
    if (mouse->handle < 0)
        return -1;
    int flags = DEVICE_NOWAIT;
    DeviceDevCtl(mouse->handle, MOUSEIO_SETFLAGS, &flags);
    return 0;
}

int ViewMouseClose(view_mouse_t *mouse)
{
    int flags;
    DeviceDevCtl(mouse->handle, MOUSEIO_GETFLAGS, &flags);
    flags &= ~DEVICE_NOWAIT;
    DeviceDevCtl(mouse->handle, MOUSEIO_SETFLAGS, &flags);
    return DeviceClose(mouse->handle);
}

int __attribute__((optimize("00"))) ViewMouseRead(view_mouse_t *mouse)
{
    static int x_rel = 0;
    static int y_rel = 0;
    static int z_rel = 0;
    static int flags_rel = 0;
    input_event_t event;
    int ret = 0;
next:
    memset(&event, 0, sizeof(input_event_t));
    ret = DeviceRead(mouse->handle,&event,sizeof(input_event_t),0);
    if (ret < 0)
        return -1;

    //KPrint("[view] mouse event: event type %d code %d value %d\n", event.type, event.code, event.value);
    #if 1
    switch (event.type)
    {
    case EVENT_REL:
        if (event.code == REL_X)
        {
            x_rel += event.value;
            flags_rel = 1;
            goto next;
        }
        else
        {
            if (event.code == REL_Y)
            {
                y_rel += event.value;
                flags_rel = 1;
                goto next;
            }
            else
            {
                if (event.code == REL_WHEEL)
                {
                    z_rel = event.value;
                    mouse->wheel(z_rel < 0 ? 0 : 1);
                    return 0;
                }
            }
        }
        break;
    case EVENT_KEY:
        if (event.code == BTN_LEFT)
        {
#ifdef DEBUG_MOUSE_HAL
            KPrint("[mouse] mouse left\n");
#endif
            if (event.value > 0)
                mouse->button_down(0);
            else
                mouse->button_up(0);
            return 0;
        }
        else
        {
            if (event.code == BTN_MIDDLE)
            {
#ifdef DEBUG_MOUSE_HAL
                KPrint("[mouse] mouse middle\n");
#endif
                if (event.value > 0)
                    mouse->button_down(1);
                else
                    mouse->button_up(1);
                return 0;
            }
            else
            {
                if (event.code == BTN_RIGHT)
                {
#ifdef DEBUG_MOUSE_HAL
                    KPrint("[mouse] mouse right\n");
#endif
                    if (event.value > 0)
                        mouse->button_down(2);
                    else
                        mouse->button_up(2);
                    return 0;
                }
                else
                {
                    return 0;
                }
            }
        }
        break;
    case EVENT_MSC:
        return 0;
    case EVENT_SYN:
        mouse->x += x_rel;
        mouse->y += -y_rel;
   
        x_rel=y_rel=0;

        if (flags_rel)
        {
#ifdef DEBUG_MOUSE_HAL
            KPrint("[view] mouse move update x %d,y%d\n", mouse->x, mouse->y);
#endif
            mouse->motion();
            flags_rel = 0;
            return 0;
        }
        return 0;
        break;
    default:
        break;
    }
    #endif
    return 0;
}
